package com.common.util;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import com.common.dao.util.IDGenerator;
import com.common.model.action.Session;
import com.common.model.util.UserType;
@Deprecated
public class SessionContainer {

	private static final List<Session> sessions = new ArrayList<Session>();
	private static final Long EXPIRE_TIME = 900000L; //15 minutes
	public static String testValue;
	
	private SessionContainer() {}
	
	public static List<Session> getAll() {
		return sessions;
	}
	
	public static void addSession(Session session) {
		synchronized (sessions) {
			sessions.add(session);
		}
	}
	
	/**
	 * Create a new session with a random generated id.
	 * 
	 * @param userId
	 * @return sessionId
	 */
	public static String createSession(Long userId, UserType userType) {
		Session session = new Session();
		
		session.setId(IDGenerator.generateID());
		session.setUserId(userId);
		session.setUserType(userType);
		session.setTime(new GregorianCalendar());
		
		synchronized (sessions) {
			sessions.add(session);
		}
		
		return session.getId();
	}

	/**
	 * Get the session by it's sessionId. It will return null if not found.
	 * 
	 * @param id
	 * @return Session/null
	 */
	public static Session getSession(String id) {
		synchronized (sessions) {
			for (Session session : sessions) {
				if (session.getId().equals(id)) {
					return session;
				}
			}
		}
		return null;
	}
	
	public static Session getSession(Long userId) {
		synchronized (sessions) {
			for (Session session : sessions) {
				if (session.getUserId().equals(userId)) {
					return session;
				}
			}
		}
		return null;
	}
	
	public static String getSessionId(Long userId) {
		synchronized (sessions) {
			for (Session session : sessions) {
				if (session.getUserId().equals(userId)) {
					return session.getId();
				}
			}
		}
		return null;
	}
	
	/**
	 * Get the user's id by it's session
	 * 
	 * @param sessionId
	 * @return userId/null
	 */
	public static Long getUserId(String sessionId) {
		synchronized (sessions) {
			for (Session session : sessions) {
				if (session.getId().equals(sessionId)) {
					return session.getUserId();
				}
			}
		}
		return null;
	}
	
	public static UserType getUserType(String sessionId) {
		synchronized (sessions) {
			for (Session session : sessions) {
				if (session.getId().equals(sessionId)) {
					return session.getUserType();
				}
			}
		}
		return null;
	}
	
	/**
	 * Get the session with the given userId and delete it.
	 * 
	 * @param userId
	 * @return sessionId
	 */
	public static String getAndDeleteSession(Long userId) {
		synchronized (sessions) {
			for (Session session : sessions) {
				if (session.getUserId().equals(userId)) {
					String sessionId = session.getId();
					sessions.remove(session);
					return sessionId;
				}
			}
		}
		return null;
	}
	
	/**
	 * Delete all the session that are idle for more than EXPIRED_TIME time and 
	 * return a list with all of the user's id.
	 * 
	 * @return
	 */
	public static List<Long> getAndDeleteExpiredSessions() {
		List<Long> list = new ArrayList<Long>();
		Calendar calendar = new GregorianCalendar();
		
		synchronized (sessions) {
			for (int i = 0; i < sessions.size(); i++) {
				if (calendar.getTimeInMillis() - sessions.get(i).getTime().getTimeInMillis() > EXPIRE_TIME) {
					list.add(sessions.remove(i).getUserId());
					i--;
				}
			}
		}
		return list;
	}
	
	public static void deleteSession(Session session) {
		synchronized (sessions) {
			sessions.remove(session);
		}
	}
	
	public static void deleteSession(String sessionId) {
		synchronized (sessions) {
			for (Session session : sessions) {
				if (session.getId().equals(sessionId)) {
					sessions.remove(session);
					return;
				}
			}
		}
	}
	
	public static void deleteSession(Long userId) {
		synchronized (sessions) {
			for (Session session : sessions) {
				if (session.getUserId().equals(userId)) {
					sessions.remove(session);
					return;
				}
			}
		}
	}
	
	/**
	 * Delete all the sessions that are idle for more than EXPIRED_TIME time.
	 */
	public static void deleteExpiredSessions() {
		Calendar calendar = new GregorianCalendar();

		synchronized (sessions) {
			for (int i = 0; i < sessions.size(); i++) {
				if (calendar.getTimeInMillis() - sessions.get(i).getTime().getTimeInMillis() > EXPIRE_TIME) {
					sessions.remove(i);
					i--;
				}
			}
		}
	}
	
	public static int size() {
		return sessions.size();
	}
	
	/**
	 * Checks if the provided session exists in the SessionContainer
	 * 
	 * @param session
	 * @return true/false
	 */
	public static boolean contains(Session session) {
		return sessions.contains(session);
	}
	
	public static boolean contains(Long id) {
		synchronized (sessions) {
			for (Session session : sessions) {
				if (session.getId().equals(id)) {
					return true;
				}
			}
		}
		return false;
	}
	
	/**
	 * Checks if the session with the provided id and the provided userId 
	 * exists in the SessionContainer
	 * 
	 * @param id - session id
	 * @param userId
	 * @return true/false
	 */
	@Deprecated
	public static boolean contains(String id, Long userId) {
		synchronized (sessions) {
			for (Session session : sessions) {
				if (session.getId().equals(id) && session.getUserId().equals(userId)) {
					return true;
				}
			}
		}
		return false;
	}
	
	/**
	 * Check if the session with the given id exists in the SessionContainer 
	 * and if it does, refresh it's timer.
	 * 
	 * @param id - session id
	 * @return true/false
	 */
	public static boolean containsAndRefresh(String id) {
		synchronized (sessions) {
			for (Session session : sessions) {
				if (session.getId().equals(id)) {
					session.setTime(new GregorianCalendar());
					return true;
				}
			}
		}
		return false;
	}
	
	/**
	 * Check if the session with the given id and the given userId exists in the 
	 * SessionContainer and if it does refresh it's timer.
	 * 
	 * @param id
	 * @param userId
	 * @return true/false
	 */
	@Deprecated
	public static boolean containsAndRefresh(String id, Long userId) {
		synchronized (sessions) {
			for (Session session : sessions) {
				if (session.getId().equals(id) && session.getUserId().equals(userId)) {
					session.setTime(new GregorianCalendar());
					return true;
				}
			}
		}
		return false;
	}
}
